#!/bin/bash
# Start/stop/restart unRAID.

if [ ${DEBUG:=0} -gt 0 ]
   then set -x -v
fi

P=${0##*/}              # basename of program
R=${0%%$P}              # dirname of program

# Set Your LOG directory here
LOGDIR=/boot/logs

# Set amount of syslogs you want to keep.
# Number of syslogs to save in logdir
LOGSAVE="10"

# If the LOG directory does not exist, make it!
[ ! -d ${LOGDIR} ] && mkdir -p ${LOGDIR}

PATH=$PATH:/sbin:/usr/sbin:/boot/custom/bin
ACTIVEPIDS="no"

# Alter this to NO or anything other then YES
# To disable calls to these diagnostics
SMARTCTL=${SMARTCTL:=YES}
HDPARM=${HDPARM:=YES}

# Source external file to replace anything that is defined
if [ -f /etc/${P} ]
   then source /etc/${P}
fi


logger()
{
  typeset F=${1##-t*}

  if [ "${F}" != "${1}" ]
     then F=""
     else F="-t${P}"
  fi

  # /usr/bin/logger -is -plocal7.info ${F} $*
  /usr/bin/logger -i -plocal7.info ${F} $*
}


diagnostic_dump()
{
    echo "Capturing information to syslog. Please wait..."

    logger -tversion -s < /proc/version
    logger -tcmdline    < /proc/cmdline
    logger -tmeminfo    < /proc/meminfo
    logger -tdevices    < /proc/devices
    logger -tinterrupts < /proc/interrupts
    logger -tioports    < /proc/ioports
    logger -tdma        < /proc/dma
    logger -tmounts     < /proc/mounts
    logger -tdiskstats  < /proc/diskstats

    if [ "${HDPARM}" = "YES" ] ; then
       ls -1 2>/dev/null /dev/sd[a-z] /dev/hd[a-z] | while read DEVICE
       do hdparm -I -i ${DEVICE}
       done 2>&1 | logger -thdparm
    fi

    if [ "${SMARTCTL}" = "YES" ] ; then
       ls -1 2>/dev/null /dev/sd[a-z] /dev/hd[a-z]  | while read DEVICE
       do smartctl -n standby -d ata -a ${DEVICE}
       done 2>&1 | sed 's/\t/        /g' | logger -tsmartctl
    fi

    lspci          2>&1 | logger -tpspci
    lsmod          2>&1 | logger -tlsmod
    ifconfig eth0  2>&1 | logger -tifconfig

    ( ethtool eth0 ; ethtool -S eth0 ) |
      sed 's/\t/        /g' 2>&1 | logger -tethtool

    BC=/boot/config
    for FILE in ${BC}/*.cfg ${BC}/shares/*
    do  BFILE="${FILE##*/}"  # Basename of FILE
        logger -t"${BFILE}" < "${FILE}"
    done

    if [ -e /proc/mdcmd ]
       then echo status > /proc/mdcmd
            sleep 1
            logger -tmdcmd < /proc/mdcmd
    fi

    unRAID_status       | logger -tstatus -s

}

save_syslog()
{
    TS="%Y%m%d-%H%M%S"
    LOGDATE=`ls -l --time-style="+${TS}" /var/log/syslog | cut -d' ' -f6`
    LOGNAME="${LOGDIR}/syslog-${LOGDATE}.txt"

    # Save only the $LOGSAVE number of current files
    i=0
    ls -1t ${LOGDIR}/syslog*.txt | while read SYSLOG
    do  ((i++))
        if [ $i -gt ${LOGSAVE} ]
           then echo "Removing old syslog: ${SYSLOG}"
                rm -f ${SYSLOG}
        fi
    done

    # logger "Saving current syslog to ${LOGNAME}"
    echo "Saving current syslog: ${LOGNAME}"
    todos < /var/log/syslog > "${LOGNAME}"
    touch --reference=/var/log/syslog ${LOGNAME}
    chmod a-x ${LOGNAME}
    ls -l "${LOGNAME}"

    # Save latest syslog in a .zip archive for uploading
    # logger "zipping current syslog to ${LOGDIR}/syslog.zip"
    # only zip a new syslog.txt if syslog newer then current .zip

    if [ ! -x /usr/bin/zip ]
       then echo "zip not installed. Consider installing to automatically zip current syslog"
            return
    fi

    if [ /var/log/syslog -nt ${LOGDIR}/syslog.zip ]
       then cd /var/log
            # make a symlink to syslog.txt for windows viewing
            ln -s  syslog syslog.txt
            rm -f  ${LOGDIR}/syslog.zip
            # -o (set .zip time to mtime of syslog)
            # -l (convert lf to crlf on the fly!)
            zip -o -l ${LOGDIR}/syslog.zip syslog.txt
            rm -f  syslog.txt  # remove symlink
            chmod a-x ${LOGDIR}/syslog.zip # remove samba attributes
    fi
}

# Start unraid:
unRAID_start()
{
    logger "Starting unRAID."

    SD_RCFILE=/etc/rc.d/rc.local_shutdown
    RCFILE=/etc/rc.d/rc.unRAID

    if ! grep ${RCFILE} ${SD_RCFILE} >/dev/null 2>&1
       then echo -e "\n\n[ -x ${RCFILE} ] && ${RCFILE} stop\n" >> ${SD_RCFILE}
    fi

    [ ! -x ${SD_RCFILE} ] && chmod u+x ${SD_RCFILE}

}

# Stop unraid:
unRAID_stop()
{
    # lines added by SlrG
    logger "Stopping Plugins."
    comm -13 <(sort -u < "/etc/rc.d/rcdstock") <(ls -- "/etc/rc.d") | while read line; do echo Sending \"/etc/rc.d/$line stop\"; /etc/rc.d/$line stop; done
    # end of lines added by SlrG

    logger "Stopping unRAID."

    diagnostic_dump

    [ -x /etc/rc.d/init.d/vmware  ] && /etc/rc.d/init.d/vmware stop
    [ -x /etc/rc.d/rc.samba ] && /etc/rc.d/rc.samba stop
    [ -x /etc/rc.d/rc.nfsd  ] && /etc/rc.d/rc.nfsd  stop

	if [ $ACTIVEPIDS = "yes" ]
	then
		logger "Killing active pids on the array drives"
		for fs in /mnt/user /mnt/disk*
		do  [ ! -d ${fs} ] && continue
			for signal in TERM TERM KILL
			do  for pid in $(fuser -cu $fs 2>/dev/null)
				do  ps --no-headers -fp ${pid}
					if kill -0 ${pid} 2>/dev/null
					   then kill -${signal} ${pid}
					fi
				done
				[ ! -z "${pid}" ] && sleep 1
			done
		done 2>&1 | logger
    fi

    logger "Umounting the drives"
    for disk in /mnt/disk*
    do  /bin/umount -v ${disk}
    done 2>&1 | logger

    sync

    if [ -e /proc/mdcmd ]
       then logger "Stopping the Array"
            echo status > /proc/mdcmd
            cat < /proc/mdcmd | tr -d '\000' > /tmp/mdcmd.$$.1
            echo stop > /proc/mdcmd 2>/dev/null
            sleep 3
            echo status > /proc/mdcmd
            cat < /proc/mdcmd | tr -d '\000' > /tmp/mdcmd.$$.2
            diff -u /tmp/mdcmd.$$.1 /tmp/mdcmd.$$.2 | logger -t mdstatusdiff
            rm   -f /tmp/mdcmd.$$.1 /tmp/mdcmd.$$.2
    fi

    save_syslog

    # killall emhttp

}

# Restart unRAID:
unRAID_restart()
{
    unRAID_stop
    sleep 1
    unRAID_start
}



load_mdstatus()
{
    [ ${DEBUG:=0} -gt 2 ] && set -x -v
    OFS="${IFS}"  # Save IFS

    MDCMDTMP="/tmp/mdcmd.$$"
    # create tmp output, set trap for rm on exit
    touch ${MDCMDTMP}
    trap "rm -f ${MDCMDTMP}" EXIT HUP INT QUIT TERM

    # save status command
    # if $1 is defined, use that, otherwise use /proc/mdcmd
    # this is for testing using a saved or static output of mdcmd
    if [ ! -z "${1}" ]
       then MDCMD="${1}"
       else MDCMD="/proc/mdcmd"
            [ -e ${MDCMD} ] && echo status > ${MDCMD}
    fi
    if [ -e ${MDCMD} ]
       then cat < ${MDCMD} > ${MDCMDTMP}
       else echo "mdcmd; ${MDCMD} does not exist" >&2
    fi

    # Reset IFS to add = sign
    IFS=" =
"

    # Read TMP file assigning shell variables from mdcmd variables
    MDI=0  # Set starting point for indexed variables
    while read LINE
    do  [ -z "${LINE}" ] && continue
        VAR="${LINE%=*}"   # Separate var from var=value
        VALUE="${LINE#*=}" # separate value from var=value
        VARI="${VAR%\.*}"  # separate .#  from var
        if [ "${VARI}" = "${VAR}" ]
           then eval "${VAR}='${VALUE}'"
                continue
        fi
        MDI="${VAR#*\.}"
        eval "${VARI}[$MDI]='${VALUE}'"
    done < ${MDCMDTMP}

    rm -f ${MDCMDTMP}

    IFS="${OFS}"
}


# Show unRAID status;
unRAID_status()
{
    load_mdstatus $@
    printf "State: ${mdState}\n"
    if [ "${mdResyncPrcnt}" != "" ]
       then printf "Parity CHECK in progress, %s%% complete, est. finish in %s minutes.\n" "$mdResyncPrcnt" "$mdResyncFinish"
    fi
    typeset i=0
    printf "%-2s %15.15s / %-15.15s %-14s %-9.9s %s\n" "D#" "Model" "Serial" "Status" "Device" # "Type"
    while (( ${i} <= ${MDI} ))
    do
        printf "%-2s %15.15s / %-15.15s %-14s %-9.9s %s\n" "${i}" \
        "${rdevModel[$i]}" "${rdevSerial[$i]}" \
        "${rdevStatus[$i]}" "${rdevName[$i]}" # "${rdevType[$i]}"
        if [ "${rdevStatus[$i]}" = "DISK_WRONG" ]; then
           printf "   %15.15s-%-15.15s <-- was the old disk in slot %s\n" \
                  "${diskModel[$i]}" "${diskSerial[$i]}" "$i"
        fi
        (( i++ ))
    done

    if [ "${SMARTCTL}" = "YES" ]; then
       echo "SMART overall health assessment"
       ls -1 2>/dev/null /dev/sd[a-z] /dev/hd[a-z]  | while read DEVICE
       do echo -e "${DEVICE}: \c"
          smartctl -n standby -H ${DEVICE} 2>&1 | egrep -v 'Home|===|^$|smartctl version|mandatory SMART' 
       done
    fi

    # echo "Services which may be active on the Array"
    # [ -x /etc/rc.d/init.d/vmware  ] && /etc/rc.d/init.d/vmware status
    # [ -x /etc/rc.d/rc.samba ] && /etc/rc.d/rc.samba status
    # [ -x /etc/rc.d/rc.nfsd  ] && /etc/rc.d/rc.nfsd  status

    # find active pids on array save to tmp file
    # so size (-s) can be tested and print if > 0
    PSTMP="/tmp/ps.$$"
    for fs in /mnt/user /mnt/disk*
    do  [ ! -d ${fs} ] && continue
        for pid in $(fuser -cu $fs 2>/dev/null)
        do  ps --no-headers -fp ${pid}
        done > ${PSTMP}
    done
    ACTIVEPIDS="no"
    if [ -s "${PSTMP}" ]
       then echo -e "ACTIVE PIDS on the array"
            cat < ${PSTMP}
			ACTIVEPIDS="yes"
       else echo -e "No active PIDS on the array"
    fi
    rm -f ${PSTMP}
}

case "$1" in
    'start'  ) unRAID_start   ;;
    'stop'   ) unRAID_stop    ;;
    'restart') unRAID_restart ;;
    'install') unRAID_install ;;
    'syslog' ) diagnostic_dump; save_syslog ;;
    'status' ) shift; unRAID_status $@;;
    'msg'    ) shift; logger $@;;
    *) echo "usage $0 start|stop|restart|syslog|status";;
esac
